package com.gxa.autoparts.portal.service.impl;

import com.gxa.autoparts.core.common.ExceptionCode;
import com.gxa.autoparts.core.common.GoodsVo;
import com.gxa.autoparts.core.common.JsonResult;
import com.gxa.autoparts.core.exception.BusinessException;
import com.gxa.autoparts.core.pojo.*;
import com.gxa.autoparts.core.util.JsonUtil;
import com.gxa.autoparts.portal.common.GoodsTurn;
import com.gxa.autoparts.portal.mapper.*;
import com.gxa.autoparts.portal.repository.GoodsVoRepository;
import com.gxa.autoparts.portal.service.AttributeKeyService;
import com.gxa.autoparts.portal.service.CommentService;
import com.gxa.autoparts.portal.service.GoodService;
import com.gxa.autoparts.portal.service.UserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.HashOperations;
import org.springframework.data.redis.core.ListOperations;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.ZSetOperations;
import org.springframework.stereotype.Service;
import tk.mybatis.mapper.entity.Example;

import java.net.URISyntaxException;
import java.util.*;
import java.util.concurrent.TimeUnit;

/**
 * @author ：looker
 * @date ：Created in 2022/1/6 11:02
 */
@Service
public class GoodServiceImpl implements GoodService {

    //redis中商品缓存hash的key头
    private final static String GOODHEAD = "GOOD:";

    private final static String HOTGOOD = "HOTGOOD";

    final static String GOODSKU = "GOODSKU:";

    final static String SKU = "SKU:";




    @Autowired
    RedisTemplate<String,Object> redisTemplate;

    @Autowired
    GoodsVoRepository goodsDao;

    @Autowired
    GoodsTypeMapper goodsTypeMapper;

    @Autowired
    GoodsMapper goodsMapper;

    @Autowired
    CommentService commentService;

    @Autowired
    SecondKillMapper secondKillMapper;

//    @Autowired
//    GoodService goodService;

    @Autowired
    GoodsSkuMapper goodsSkuMapper;

    @Autowired
    AttributeKeyMapper attributeKeyMapper;

    @Autowired
    AttributeValueMapper attributeValueMapper;

    @Autowired
    AttributeKeyService attributeKeyService;


    public void incrementHot(Long id){
        ZSetOperations<String, Object> operations = redisTemplate.opsForZSet();
        //商品热度加1
        Set<Object> hotgood = operations.rangeByScore("HOTGOOD", 0, Double.MAX_VALUE);
        boolean flag = true;
        for (Object o : hotgood) {
            if (o.toString().equals(""+id)) {
                operations.incrementScore("HOTGOOD",id,1);
                flag = false;
                break;
            }
        }
        if (flag) {
            operations.add("HOTGOOD",id,1);
        }
    }

    @Override
    public Map searchById(Long id) throws URISyntaxException {
        HashMap<String, Object> data = new HashMap<>();

        HashOperations hashOperations = redisTemplate.opsForHash();

        //取商品信息
        Goods goods = null;
        Boolean aBoolean2 = redisTemplate.hasKey(GOODHEAD + id);
        Map entries = null;
        if(!aBoolean2){
            Goods goods2 = goodsMapper.selectByPrimaryKey(id);
            if(goods2==null){
                Goods goods1 = new Goods();
                goods1.setId(id);
                hashOperations.put(GOODHEAD+id,"id",id);
                redisTemplate.expire(GOODHEAD+id,10, TimeUnit.MINUTES);
                goods = goods1;
            }else {
                goods = goods2;
                incrementHot(id);
                String s = JsonUtil.ObjectToString(goods);
                Map map = JsonUtil.readToObject(s, Map.class);
                hashOperations.putAll(GOODHEAD+id,map);
            }

        }else {
            entries = hashOperations.entries(GOODHEAD + id);
            //不为空准备返回
            incrementHot(id);
            goods = JsonUtil.mapToObject(entries, Goods.class);
        }

        data.put("good",goods);

        List<Object> imgs = commentService.getImgs(id);
        data.put("imgs",imgs);
        List<Comment> comments = commentService.getComments(id);
        data.put("comments",comments);
        List<Object> keyWords = commentService.getKeyWords(id);
        data.put("keywords",keyWords);
        Boolean resovle = commentService.isResovle(id);
        data.put("isResovle",resovle);

        return data;
    }

    @Override
    public Goods searchGoodById(Long id) {
        HashOperations<String, Object, Object> hashOperations = redisTemplate.opsForHash();
        Map<Object, Object> entries = hashOperations.entries(GOODHEAD + id);
        Goods goods = null;
        if(entries.size()==0){
            //redis中不存在
            goods = goodsMapper.selectByPrimaryKey(id);
            if(goods==null){
                //数据库中也不存在
                goods = new Goods();
                goods.setId(id);
            }
            String s = JsonUtil.ObjectToString(goods);
            Map map = JsonUtil.readToObject(s, Map.class);
            hashOperations.putAll(GOODHEAD+id,map);
        }else {
            goods = JsonUtil.mapToObject(entries, Goods.class);
        }
        return goods;
    }

    @Override
    public List<GoodsVo> searchByWord(String word) {
        if(word==null){
            word = "";
        }
        List<GoodsVo> goodsVoByNameContains = goodsDao.findGoodsVoByNameContains(word);
        return goodsVoByNameContains;
    }

    @Override
    public List<GoodsVo> searchCommon(String word, Long typeId) {
        List<GoodsVo> goods = null;
        if(word==null){
            word = "";
        }
        if(typeId==null){
            goods = goodsDao.findGoodsVoByNameContains(word);
        }else {
            GoodsType goodsType = goodsTypeMapper.selectByPrimaryKey(typeId);
            //是否为一级分类
            if (goodsType.getPid()!=0) {
                goods = goodsDao.findGoodsVoByNameContainsAndTypeIdEquals(word,typeId);
            }else {
                //不是一级则需要找出该大分类下的所有小分类，并查出这些小分类的所有商品
                Example example = new Example(GoodsType.class);
                Example.Criteria criteria = example.createCriteria();
                criteria.andEqualTo("pid",typeId);
                List<GoodsType> goodsTypes = goodsTypeMapper.selectByExample(example);
                List<GoodsVo> goodsVos = new ArrayList<>();
                for (GoodsType type : goodsTypes) {
                    List<GoodsVo> nowLittleTypeGoods = goodsDao.findGoodsVoByNameContainsAndTypeIdEquals(word, type.getId());
                    goodsVos.addAll(nowLittleTypeGoods);
                }
                goods = goodsVos;
            }
        }
        return goods;
    }

    @Override
    public List<GoodsVo> searchBySaleCount(String word, Long typeId) {
        List<GoodsVo> goods = null;
        if(word==null){
            word = "";
        }
        if(typeId==null){
            goods = goodsDao.findGoodsVoByNameContainsOrderBySaleCountDesc(word);
        }else {
            GoodsType goodsType = goodsTypeMapper.selectByPrimaryKey(typeId);
            //是否为一级分类
            if (goodsType.getPid()!=0) {
                goods = goodsDao.findGoodsVoByNameContainsAndTypeIdEqualsOrderBySaleCountDesc(word,typeId);
            }else {
                //不是一级则需要找出该大分类下的所有小分类，并查出这些小分类的所有商品
                Example example = new Example(GoodsType.class);
                Example.Criteria criteria = example.createCriteria();
                criteria.andEqualTo("pid",typeId);
                List<GoodsType> goodsTypes = goodsTypeMapper.selectByExample(example);
                List<GoodsVo> goodsVos = new ArrayList<>();
                for (GoodsType type : goodsTypes) {
                    List<GoodsVo> nowLittleTypeGoods = goodsDao.findGoodsVoByNameContainsAndTypeIdEqualsOrderBySaleCountDesc(word,typeId);
                    goodsVos.addAll(nowLittleTypeGoods);
                }
                goods = goodsVos;
            }
        }
        return goods;
    }

    @Override
    public List<GoodsVo> searchByPriceSort(String word, Long typeId, Boolean sort) {
        List<GoodsVo> goods = null;
        if(word==null){
            word = "";
        }
        if(typeId==null){
            if(sort){
                goods = goodsDao.findGoodsVoByNameContainsOrderBySalePriceAsc(word);
            }else {
                goods = goodsDao.findGoodsVoByNameContainsOrderBySalePriceDesc(word);
            }
        }else {
            GoodsType goodsType = goodsTypeMapper.selectByPrimaryKey(typeId);
            //是否为一级分类
            if (goodsType.getPid()!=0) {
                if(sort){
                    goods = goodsDao.findGoodsVoByNameContainsAndTypeIdEqualsOrderBySalePriceAsc(word,typeId);
                }else {
                    goods = goodsDao.findGoodsVoByNameContainsAndTypeIdEqualsOrderBySalePriceDesc(word,typeId);
                }
            }else {
                //不是一级则需要找出该大分类下的所有小分类，并查出这些小分类的所有商品
                Example example = new Example(GoodsType.class);
                Example.Criteria criteria = example.createCriteria();
                criteria.andEqualTo("pid",typeId);
                List<GoodsType> goodsTypes = goodsTypeMapper.selectByExample(example);
                List<GoodsVo> goodsVos = new ArrayList<>();
                for (GoodsType type : goodsTypes) {
                    List<GoodsVo> nowLittleTypeGoods = null;
                    if(sort){
                        nowLittleTypeGoods = goodsDao.findGoodsVoByNameContainsAndTypeIdEqualsOrderBySalePriceAsc(word,typeId);
                    }else {
                        nowLittleTypeGoods = goodsDao.findGoodsVoByNameContainsAndTypeIdEqualsOrderBySalePriceDesc(word,typeId);
                    }
                    goodsVos.addAll(nowLittleTypeGoods);
                }
                goods = goodsVos;
            }
        }
        return goods;
    }

    @Override
    public void updateGoods() {
        List<Goods> goods = goodsMapper.selectAll();
        for (Goods good : goods) {
            goodsDao.save(GoodsTurn.goodsToVo(good));
        }
    }

    @Override
    public List<Goods> getBannerGoods() {
        ZSetOperations<String, Object> operations = redisTemplate.opsForZSet();
        HashOperations<String, Object, Object> hashOperations = redisTemplate.opsForHash();
        List<Goods> goodsList = new ArrayList<>();

        Set<Object> hotgood = operations.range(HOTGOOD, -3, -1);
        for (Object o : hotgood) {
            Map<Object, Object> entries = hashOperations.entries(GOODHEAD + o);
            Goods goods = JsonUtil.mapToObject(entries, Goods.class);
            goodsList.add(goods);
        }
        return goodsList;
    }

    @Override
    public List<Goods> getHotGoods() {
        ZSetOperations<String, Object> operations = redisTemplate.opsForZSet();
        HashOperations<String, Object, Object> hashOperations = redisTemplate.opsForHash();
        List<Goods> goodsList = new ArrayList<>();

        Set<Object> hotgood = operations.range(HOTGOOD, -6, -4);
        for (Object o : hotgood) {
            Map<Object, Object> entries = hashOperations.entries(GOODHEAD + o);
            Goods goods = JsonUtil.mapToObject(entries, Goods.class);
            goodsList.add(goods);
        }
        return goodsList;
    }



    @Override
    public List<Goods> getSecondKillGoods() {
        List<Goods> goodsList = new ArrayList<>();
        //查出当前时间最近的还没开始的三个秒杀
        List<SecondKill> secondKill = secondKillMapper.getSecondKill();
        //找出他们对应的商品信息
        for (SecondKill kill : secondKill) {
            Goods goods = this.searchGoodById(kill.getGoodsId());
            goodsList.add(goods);
        }
        return goodsList;
    }



    @Override
    public List<GoodsSku> getSkuById(Long goodId) {
        ListOperations<String, Object> listOperations = redisTemplate.opsForList();
        HashOperations<String, Object, Object> hashOperations = redisTemplate.opsForHash();
        //该商品的goodsku的键
        String key = GOODSKU+goodId;
        //存放商品skuid的list
        List<Object> goodsSkuId = new ArrayList<>();
        //该商品的sku
        List<GoodsSku> goodsSkus = null;

        if (!redisTemplate.hasKey(key)) {
            Example example = new Example(GoodsSku.class);
            Example.Criteria criteria = example.createCriteria();
            criteria.andEqualTo("goodsId",goodId);
            goodsSkus = goodsSkuMapper.selectByExample(example);
            if (goodsSkus.size()>0) {
                for (GoodsSku skus : goodsSkus) {
                    goodsSkuId.add(skus.getId());
                }
                listOperations.leftPushAll(key,goodsSkuId);
            }
        }else {
            //redis中有
            goodsSkus = new ArrayList<>();
            List<Object> range = listOperations.range(key, 0, -1);
            for (Object o : range) {
                GoodsSku skus = getSkus(Long.parseLong(o.toString()));
                if (skus!=null) {
                    goodsSkus.add(skus);
                }
            }
        }
        return goodsSkus;
    }


    @Override
    public List<Map<String, Object>> getStandards(Long goodId) throws BusinessException {
        List<GoodsSku> skus = this.getSkuById(goodId);
        Goods goods = this.searchGoodById(goodId);
        Long typeId = goods.getTypeId();
        //找到该商品所属分类的规格
        List<Map<String, Object>> attribute = attributeKeyService.getAttribute(skus);
        return attribute;
    }



    @Override
    public List<Map<String, Object>> getSkuJsonList(Long goodId) throws BusinessException {
        List<Map<String,Object>> arrayList = new ArrayList<>();
        List<GoodsSku> skuById = this.getSkuById(goodId);
        for (GoodsSku goodsSku : skuById) {
            HashMap<String, Object> nowSku = new HashMap<>();
            nowSku.put("skuId",goodsSku.getId());
            nowSku.put("salePrice",goodsSku.getPrice());
            nowSku.put("remarkPrice",goodsSku.getMarkPrice());
            nowSku.put("nowCount",goodsSku.getCount());
            //将具体的分类从nowProductSpecs中拿出放进nowsku
            String productSpecs = goodsSku.getProductSpecs();
            Map<String,Object> nowProductSpecs = JsonUtil.readToObject(productSpecs, Map.class);
            Set<Map.Entry<String, Object>> entries = nowProductSpecs.entrySet();
            for (Map.Entry<String, Object> entry : entries) {
                String key = entry.getKey();
                AttributeValue attributeValueByName = attributeKeyService.getAttributeValueByName(entry.getValue().toString());
                if(attributeValueByName!=null){
                    nowSku.put(key,attributeValueByName.getId());
                }else {
                    throw new BusinessException(ExceptionCode.STATE_EXIST);
                }
            }
            arrayList.add(nowSku);
        }
        return arrayList;
    }

    /**
     * 向redis中获取sku数据，如果没有，则从数据库中获取
     * @param skuId
     * @return
     */
    public GoodsSku getSkus(Long skuId){
        HashOperations<String, Object, Object> hashOperations = redisTemplate.opsForHash();
        Map<Object, Object> entries = hashOperations.entries(SKU + skuId);
        if(entries!=null && entries.size()>0){
            //redis中存在
            GoodsSku goodsSku = JsonUtil.mapToObject(entries, GoodsSku.class);
            if(goodsSku!=null){
                return goodsSku;
            }
        }else {
            GoodsSku goodsSku = goodsSkuMapper.selectByPrimaryKey(skuId);
            if(goodsSku!=null){
                //写入缓存
                String s = JsonUtil.ObjectToString(goodsSku);
                Map map = JsonUtil.readToObject(s, Map.class);
                hashOperations.putAll(SKU+skuId,map);
                return goodsSku;
            }else {
                //写入假数据
                GoodsSku goodsSku1 = new GoodsSku();
                goodsSku1.setGoodsId(skuId);
                String s = JsonUtil.ObjectToString(goodsSku1);
                Map map = JsonUtil.readToObject(s, Map.class);
                hashOperations.putAll(SKU+skuId,map);
                return null;
            }
        }
        return null;
    }
}
